#include "weather_api.h"

void weather_server_init();
static const char *TAG = "weather";
Weather weather = {
    .province_code = 1,
    .city_code = 1,
    .init = weather_server_init,
};

void http_get_task()
{
    const struct addrinfo hints = {
        .ai_family = AF_INET,
        .ai_socktype = SOCK_STREAM,
    };
    struct addrinfo *res;
    struct in_addr *addr;
    int s, r;
    char request_buf[256] = {0};
    char recv_buf[64];

    char store_buf[1024];
    uint16_t pos = 0;
    char city_name[10] = {0};
    char *json_start = NULL;

    while(1)
    {
        while(1)
        {
            ESP_LOGI(TAG, "== Weather Waiting WIFI %d ==\n", wifi.wifi_status);
            if(wifi.wifi_status == SYS_WIFI_STATUS_CONNECT_ERR)
            {
                ESP_LOGI(TAG, "== DELETE Weather TASK: out time ==\n");
                vTaskDelete(NULL);
                weather.weather_syn = 0;
                return;
            }else if(wifi.wifi_status == SYS_WIFI_STATUS_CONNECTED)
            {
                break;
            }
            delay_ms(1000);
        }
        
        int err = getaddrinfo(WEB_SERVER, "80", &hints, &res);
        if(err != 0 || res == NULL)
        {
            ESP_LOGE(TAG, "DNS lookup failed err=%d res=%p", err, res);
            delay_ms(1000);
            continue;
        }
    
        addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
        ESP_LOGI(TAG, "DNS lookup succeeded. IP=%s", inet_ntoa(*addr));

        s = socket(res->ai_family, res->ai_socktype, 0);
        if (s < 0)
        {
            ESP_LOGE(TAG, "... Failed to allocate socket.");
            freeaddrinfo(res);
            vTaskDelay(1000 / portTICK_PERIOD_MS);
            continue;
        } 
        ESP_LOGI(TAG, "... allocated socket");
        
        if (connect(s, res->ai_addr, res->ai_addrlen) != 0)
        {
            ESP_LOGE(TAG, "... socket connect failed errno=%d", errno);
            close(s);
            freeaddrinfo(res);
            delay_ms(4000);
            continue;
        }
        ESP_LOGI(TAG, "... connected");
        freeaddrinfo(res);

        code_to_city_name(weather.city_code, city_name);
        sprintf(request_buf, REQUEST, city_name);
        ESP_LOGI(TAG, "request_buf:%s\n", request_buf);

        if (write(s, request_buf, strlen(request_buf)) < 0)
        {
            ESP_LOGE(TAG, "... socket send failed");
            close(s);
            delay_ms(4000);
            continue;
        }
        ESP_LOGI(TAG, "... socket send success");

        struct timeval receiving_timeout;
        receiving_timeout.tv_sec = 5;
        receiving_timeout.tv_usec = 0;
        if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &receiving_timeout,
                       sizeof(receiving_timeout)) < 0)
        {
            ESP_LOGE(TAG, "... failed to set socket receiving timeout");
            close(s);
            delay_ms(4000);
            continue;
        }
        ESP_LOGI(TAG, "... set socket receiving timeout success");
        memset(store_buf,0,strlen(store_buf));

        /* Read HTTP response */
        do
        {
            bzero(recv_buf, sizeof(recv_buf));
            r = read(s, recv_buf, sizeof(recv_buf) - 1);
            for (int i = 0; i < r; i++)
            {
                *(store_buf + pos + i) = recv_buf[i];
                putchar(recv_buf[i]);
            }
            pos += r;
        } while (r > 0);

        ESP_LOGI(TAG, "... done reading from socket. Last read return=%d errno=%d\r\n", r, errno);
        close(s);
        //ESP_LOGI(TAG, "recv:[ %s ]\n", store_buf);

        json_start = strchr(store_buf, '{');
        //ESP_LOGI(TAG, "\n\n[ %s ]\n\n", json_start);
        cJSON *pJsonRoot = cJSON_Parse(json_start); 
        if (pJsonRoot != NULL)
        {
            cJSON *arrayItem = cJSON_GetObjectItem(pJsonRoot, "results");
            ESP_LOGI(TAG, "\nresults\n");
            if (arrayItem)
            {
                ESP_LOGI(TAG, "arrayItem\n");
                cJSON *object = cJSON_GetArrayItem(arrayItem, 0);
                //os_printf("hello\n");

                cJSON *item_now = cJSON_GetObjectItem(object, "now"); //
                cJSON *text = cJSON_GetObjectItem(item_now, "text");
                cJSON *code = cJSON_GetObjectItem(item_now, "code");
                cJSON *temperature = cJSON_GetObjectItem(item_now, "temperature");

                os_printf("text:%s\n", text->valuestring);
                os_printf("code:%s\n", code->valuestring);
                os_printf("temperature:%s\n", temperature->valuestring);

                weather.weather_code = atoi(code->valuestring);
                weather.weather_temp = atoi(temperature->valuestring);
                strncpy(weather.weather_text, text->valuestring, strlen(text->valuestring));
            }
        }
        weather.weather_syn = 1;
        if(mtime.sntp_syn == 1 && Dsystem.sys_wifi_enable == 1)
        {
            Dsystem.sys_wifi_enable = 0;
            wifi.close_wifi();
        }
        break;
    }
    vTaskDelete(NULL);
}




void weather_server_init()
{
    xTaskCreate(&http_get_task, "http_get_task", 4096, NULL, 10, NULL);
    //http_get_task();
    //http_get_task();
}